在controller寫方法時,若常常需要用到某個方法,我們會將方法直接寫在Model或上層的application_controller.rb
來取用。
已正在進行的專案為例,每個User有一台購物車,除了devise給我們現有的current_user
之外,我想在寫個current_cart
給每個controller用,此時就可以把定義current_cart
的方法寫在application_controller.rb
。
class ApplicationController < ActionController::Base
private
def current_cart
@current_cart ||= Cart.find_or_create_by(user: current_user)
end
end
但有時候並不是每個controller或Model都需要用到這個方法,尤其是把所有要用的方法寫在該類別的Model,會導致Model越來越肥,controller越來越瘦。
為了解決這個問題,rails在models下有個資料夾名稱concerns
,把定義方法寫在這,在該controller有需要的時候再引入使用就好。
新增一個檔案 usercart.rb
module Usercart
extend ActiveSupport::Concern
included do
has_one :cart
end
module ClassMethods
def search(search)
if search
where(['title || description || address LIKE ?', "%#{search}%"])
else
all
end
end
end
private
def current_cart
@current_cart ||= Cart.find_or_create_by(user: current_user)
end
end
included do ...end
當這個module被include到Model時會做的事:(一對一)有一台購物車ClassMethod
在這裡定義的方法被include時會變成類別方法:可以直接針對該Model做搜尋的方法。current_cart
被include之後會變成該類別的實體方法:如果有找到車就用這台,沒有車就生一台給user。
此時在User的Model加入:
class User < ApplicationRecord
include Usercart
end
就可以擁有在concern資料夾下內 usercart.rb 裡的方法可以用了,相對的如果你在其他的Model也想要用的話,再直接include進該Model就好。
參考資料:
How to use concerns in Rails 4
Rails 程式碼整理術(入門)
“Live today. Not yesterday. Not tomorrow. Inhabit your moments. Don’t rent them out to tomorrow.”
– Jerry Spinelli, Writer
本文同步發佈於: https://louiswuyj.tw/